V5. Controls Controls within ViewIt windows are much more powerful than the standard controls seen in Mac dialogs. This power is based upon an extension of the Control Manager that (1) stores more information about the characteristics of each control, and (2) sends a wider variety of messages to each control. This extension is what makes it possible to support multiple styles and colors, as well as complex controls such as this help control that contains its own scroll bar and can respond to a full range of events. This topic presents information about ViewIt controls that applies to all control types: how to get info about existing controls, which toolbox calls work with ViewIt controls, and ViewIt's support for control scrolling, growing, styles, colors, etc. Information about specific control types can be obtained from the corresponding driver's on-line help. To open such help, 1. Add the control of interest to a ViewIt window 2. Enter edit mode (Option-⌘-Shift) 3. Select the control (click once on it) 4. Open the Control dialog (shortcut: triple click) 5. Press the "Driver Help" button The menu controls at the top of this window, for example, are supported by the BaseCt basic control driver which has an on-line help window that describes all of the control types that it supports: text, icons, lists, menus, dials, etc. Getting Info The extra information associated with each ViewIt control is stored in a relocatable block whose handle can be found in the "contrlDefProc" field of the control's standard control record (which is itself another relocatable block). Since it would be a headache for programmers to retrieve this info from relocatable blocks, ViewIt's GetCtl command can be used to get the info from both the standard control record and the extra block (see GetCtl in "Commands" topic). GetCtl copies the content of the two blocks into the fRec variables cNext to cString, where cNext to cTitle corresponds to the standard control record, and cStuff to cString is a copy of the supplemental record. GetCtl also returns the control's control handle in cControl, info about its position in the control list in ciIndex, cvIndex, and ccIndex, and the driver's baseID in cBaseID (see the "fRec Record" topic for brief description of each variable). Common uses of GetCtl include: - getting the control handle for use in other calls - determining the current value or state of a control - getting the current control rect prior to drawing - getting the handle of a resource linked to the control WARNING: Do not assume that the content of fRec variables returned by GetCtl is preserved across calls to the Control Manager or the FaceIt dispatching procedure. Values that might need to be reused, such as a cControl control handle, should be saved in program variables. One exception: Most UtilIt commands preserve the "w" and "c" variables. Toolbox Calls Although we have greatly enhanced the capabilities of controls in ViewIt windows, most of the Control Manager toolbox calls can continue to be used with ViewIt controls. Moreover, toolbox calls applied to view controls in ViewIt windows will automatically affect all daughter controls in the view (i.e., hiding a view will also hide controls within the view). The toolbox calls supported are: HiliteControl SetCtlValue ShowControl SetCtlMin HideControl SetCtlMax Draw1Control GetCtlValue SizeControl GetCtlMin MoveControl GetCtlMax DragControl SetCRefCon GetCtlAction GetCRefCon GetCTitle SetCTitle where ViewIt's GetCtl makes the "Get..." calls unnecessary, DrwCtl can be used in place of "Draw1Control", ShoCtl in place of "ShowControl" and "HideControl", and ActCtl in place of "HiliteControl". CAVEAT: The Control Manager does not always send the proper messages to controls that are hidden. This is due to the fact that it assumes that controls redraw themselves in a simple way based upon the current state of their control record. Many ViewIt controls, however, maintain private data that must be updated whenever the control is moved, resized, or has its value or hilite state changed. With respect to moving and resizing, ViewIt makes an effort to compensate for the Control Manager by fixing a hidden control's private size-related data whenever it is reshown. When using "SetCtl..." or "HiliteControl", however, you may find that these do not work properly with complex, hidden ViewIt controls. The toolbox calls not supported are: DrawControls UpdtControl NewControl GetNewControl DisposeControl KillControls FindControl TestControl TrackControl SetCtlAction where ViewIt's AddCtl or AddVew should be used in place of "NewControl" and "GetNewControl", DspCtl in place of "DisposeControl" and "KillControls", and the others are replaced by other ViewIt features and commands. NOTE: These restrictions and substitutions only apply to ViewIt controls. Private controls maintained as part of a ViewIt control (such as the scroll bar in this help control), are treated as standard Mac controls by the control driver. Rectangles The settings displayed in ViewIt's Bounds dialog are the ones saved in FWND, FVEW, or FCTL resources. When controls are initialized from such resources, the "Pen", "Bounds", "Indent", and "Content" information from the resource is converted to the cRect, cClip, cContent, and cLimit rectangles used by ViewIt and control drivers. cRect is the standard control bounds. cClip is the visible content area of the control (= cRect - frame and indent). cLimit defines the minimum & maximum bounds of cRect when resizing the control. cContent is either the same as cClip, growing and shrinking with the control bounds, or is a fixed size that can be larger or smaller than cClip. Many control drivers ignore cContent and always draw their content to fit cClip. In this case it is best to set up cContent so that it tracks cClip. This is done by setting the "Max H" and "Max V" content values in the Bounds dialog to zero. This help control, for example, makes no use of cContent, and manages its own scrolling. Other control drivers and types do make use of cContent. The SICN-based static controls at the top of this window, for example, have non-zero "Max H" and "Max V" content values to inform the driver that their contents should not be stretched to fit cClip. Scrolling Another use of cContent is to support "hand scrolling" of a control's content. This support is built into ViewIt, and is activated by setting a non-zero "Max H" or "Max V" and checking the hand icon in the Bounds dialog. When above the control, the cursor is then changed to a hand which can be used to "hand drag" the control's contents: dragging the content down moves cContent lower relative to cClip, up moves cContent higher, etc. This feature will only work with controls that draw their contents into cContent. The most common use is to support hand dragging of the content of views, although views can also support scroll bar-based scrolling independently. Controls with content areas larger than cClip can also be scrolled directly by programs via the ScrCtl command. A program can also use ScrCtl to resize the content area of a control. This capability is most often used in programs that dynamically construct views that have a varying number of daughter controls: AddVew adds the view, ScrCtl adjusts its content size, and AddCtl adds daughter controls. Growing Controls can be "attached" to the right or bottom sides of their parent views, and views to the right or bottom sides of their parent window, by setting the "Attach Right" or "Attach Bottom" options in the Bounds dialog. If the window is zoomable or growable (options set in Window dialog), then the attached controls and views that are not of a fixed size ("Min H" ≠ "Max H" or "Min V" ≠ "Max V") are used to determine the minimum and maximum window size (via the control or view's cLimit rectangle described above). This help window, for example, contains one view that is attached to the bottom and right sides of the window, and a help control that is attached to the bottom and right sides of the view. If the window size is changed, then the attached view and control are resized to fit the new window size. Also note that attached controls are aligned with the right edge of the parent view's visible content area, which explains why, in the case of this window, the help control is indented a few pixels from the view's edges (the view has a 3-pixel right and bottom indent). Although ViewIt makes growing and zooming quite easy to implement, there are a few guidelines you should follow to achieve the best results: • If the window is growable or zoomable, then at least one view in the window should be attached to both the bottom and right sides of the window. • If more than one view is attached to the both the bottom and right sides of the window (such as when supporting the "paging" of views), then each of these overlapping views should have the same frame and indent size. This ensures that the grow box is drawn properly as views are switched. • Do not attach controls to views that are set up to be hand scrolled or scrolled via scroll bars (think about it). Such views can themselves, however, be attached to windows. • ViewIt does not protect you from adding attached controls or views whose limits cannot be reconciled (i.e., when one control's maximum size is smaller than another control's minimum size). Strange zoom or grow behavior will result in such cases. • ViewIt updates window and control size limits according to the attached controls and views in just two cases: (1) when windows are created, and (2) when leaving editing mode. If your program adds, removes, moves, or resizes (including resizing the content area with ScrCtl) attached controls or views using ViewIt or toolbox commands, then call SizWnd with b = c = 0 to force ViewIt to update all attachments. This requirement does not apply to hiding and showing. Floating Controls that are attached to the right or bottom sides of their parent view or window, but are of a fixed size ("Min H" = "Max H" or "Min V" = "Max V"), will appear to "float" with the right or bottom edge as the parent view or window is resized (i.e., they remain attached by moving rather than stretching). Two of the guidelines given above also apply to floating controls: • Do not attach floating controls to views that are set up to be hand scrolled or scrolled via scroll bars. • ViewIt updates the position of floating controls or views at the same time that it updates the size of attached controls or views that grow with their parent view or window. Styles Each control has a text font, size, and style associated with it. This information is found, respectively, in cTxFont, cTxSize, and cTxFace after calling GetCtl, and can be reset from within ViewIt's edit mode via its Style menu. ViewIt's StlCtl command can be used by a program to directly reset the text font, size, or style of an existing control (see Commands topic). This is equivalent to using ViewIt's Style menu, and results in redrawing the control. Colors Each "part" of a control can be a different color. With the introduction of System 7, Apple defined 15 distinct control parts corresponding to the 15 items in ViewIt's Color menu. Most control drivers support the first three of these colors: frame, body (background), and content. The "System" or default colors for these parts are black frame, white body, and black content. If the "System" item is checked in the Colors menu, then the control uses the default colors and its cColors handle will be nil. If at least one color has been chosen from the Colors menu for a control part (even if it is the same color as the part's default color), then ViewIt creates a control color table for the control, a handle to which can be found in cColors (after calling GetCtl). cColors is a handle to a relocatable block that has the following structure: 6 bytes miscellaneous stuff 2-byte integer = number of entries - 1 2-byte integer = part number 6-byte RGBColor = part color 2-byte integer = part number 6-byte RGBColor = part color ... where the "part numbers" for frame, body, and content are, respectively, 0, 1, and 2. Although there are toolbox calls that can be used to reset control color tables, the simplest way to manipulate control colors from within a program is to simply get/set colors in an existing table. This approach requires that the control being manipulated has a non-empty color table, which can be assured by directly setting at least one part color using ViewIt's Colors menu when in editing mode. The UtilIt command GetFgC can be used to get a color from a cColors table: FaceIt(nil,GetFgC,0,-2,ord(cColors),2); where "2" in this case is the part number corresponding to the control's content, and the color is returned in uRGB. To directly reset a color, the color entry with the proper part number must be found. In Pascal, such a search would look something like (if cColors is type "CCTabHandle"), if (cColors <> nil) then with cColors^^ do for i := 0 to ctSize do if (ctTable[i].value = 2) then begin ctTable[i].rgb := newColor; leave; end; where "2" refers to the content part, "newColor" will be the new RGB color of the control's content, and DrwCtl can be used to then redraw the control. Best Colors For the best appearance across all types of Macintoshes, use relatively light body (background) colors (such as the yellow in this control), and darker content and frame colors. This will ensure that control backgrounds do not turn to black on black-and-white screens, and that content and frames do not become white. The reverse use of darker backgrounds and lighter content and frames does not map well to lower screen depths. Also note that, when testing the display of control colors at different screen depths, the appearance of a control on a one-bit deep black-and-white device with Color QuickDraw installed will not always be the same as its appearance on a Mac without Color QuickDraw (such as a Mac+). Always check the appearance of colored controls at varying screen depths, in both color and non-color windows, and on older Macs without Color QuickDraw.